package dmon;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * Universidad Simón Bolívar
 * Curso de Redes I - Taller
 * Profesor: Ricardo Gonzalez
 * Trimestre Enero-Marzo 2011
 *
 * Proyecto 2 RD
 *
 * @author Grupo 9
 * @author Richard Simoes Ferreira
 * @author Ricardo Tocco
 *
 * @version 1.0
 */
public class ServiceDmon extends Thread {

 /**
 * Implementación de un servicio que se ofrece a un cliente del servidor dmon
 */
    private Socket cliente = null;
    private ControlDmon control;
    /**
     * Constructor de ServiceDmon
     * @param s Socket del cliente al cual se le ofrece el servicio
     * @param c Estructura de control dmon que contine los diferentes servicios
     */
    public ServiceDmon (Socket s, ControlDmon c){
        this.cliente = s;
        this.control = c;
    }

    /**
     * Código que ejecuta el hilo encargado de implementar el servicio
     */
    @Override
    public void run(){
        ErrorHandler errorH = new ErrorHandler();
        boolean fin = false;
        while (!fin){
            try {
                //Escuchar Peticion (Protocolo)
                //Responder Peticion
                //Termina

                String solicitud;
                String header = Getlinea();
                String argumentos[];
                //Se segmenta el mensaje de acuerdo con el separador del
                //protocolo
                argumentos = header.split("\\##%");
                solicitud = argumentos[0];

                if (solicitud.equals("newDrep")){
                    //Se ha conectado un nuevo drep
                    //Segun el protocolo le respondemos check
                    control.incrementarActivosDrep();
                    sendLinea("check");

                } else if (solicitud.equals("tuser")) {
                //Se solicita mostrar todos los nombres de usuarios dcli activados
                //Segun el protocolo le respondemos con la lista de usuarios dcli
                //conectados
                    LinkedList<String> usuariosDcli = control.getActivosDcli();
                    Iterator<String> listaUsr = usuariosDcli.descendingIterator();
                    if (usuariosDcli.isEmpty()){
                        //Directorio no existe o no es un directorio
                        sendLinea("noExistenUsuarios");
                    } else {
                        String s = "";
                        while(listaUsr.hasNext()){
                            s += listaUsr.next()+"##%";
                        }
                        sendLinea(s);
                    }
                } else if (solicitud.equals("nrep")){
                    //Se solicita el numero de drep activados
                    //Segun el protocolo le respondemos con el numero de drep activos
                    String response = String.valueOf(control.getActivosDrep());
                    if (response!=null){
                        sendLinea(response);
                    }else {
                        sendLinea("error");
                    }
                } else if (solicitud.equals("subida")){
                    //Se envia información de una nueva subida de archivo al
                    //servidor tokens.nextToken()
                    control.incrementarSubidosDrep();
                } else if (solicitud.equals("bajada")){
                    //Se envia información de una nueva bajada de archivo al
                    //servidor tokens.nextToken()
                    control.incrementarBajadosDrep();
                } else if (solicitud.equals("newDcli")){
                    //Se envia información sobre la conexion de un dcli 
                    //llamado tokens.nextToken()
                    int status = -1;

                    if (argumentos.length<2){
                        sendLinea("error parametros");
                    } else {
                        status = control.incrementarActivosDcli(argumentos[1]);
                    }
                   
                    if (status < 0) {
                        sendLinea("error");
                    } else {
                        sendLinea("check");
                    }
                } else if (solicitud.equals("disconnectDcli")){
                    //Se envia información sobre la desconexion de un dcli 
                    //llamado tokens.nextToken()
                    int status = -1;

                    if (argumentos.length<2){
                        sendLinea("error parametros");
                    } else {
                        status = control.decrementarActivosDcli(argumentos[1]);
                    }

                    if (status < 0) {
                        sendLinea("error");
                    } else {
                        sendLinea("check");
                    }
                } else if (solicitud.equals("disconnectDrep")){
                    //Se envia información sobre la desconexion de un drep
                    control.decrementarActivosDrep();
                    sendLinea("check");
                    cliente.close();
                    fin = true;
                    
                } else {
                    //No se entendio la solicitud
                }

            } catch (IOException ex) {
                errorH.errorGetLineaDrep(control, cliente);
            }
        }
        

    }
    /**
     * Obtiene una linea del flujo de comunicación enviado desde el servidor
     * drep
     * @return  Linea capturada a través del socket de comunicación
     */
    public String Getlinea() {

        String buf;
        ErrorHandler errorH = new ErrorHandler();

        try {

            BufferedReader in = new BufferedReader(new InputStreamReader(this.cliente.getInputStream()));

            if((buf=in.readLine()) != null){
                return buf;
            } else {
                //Problemas de comunicación
                errorH.errorBufferGetLineaDrep(this.control,this.cliente);

                return "disconnectDrep";
            }

        } catch (IOException e){
            errorH.errorGetLineaDrep(this.control,this.cliente);
            return null;
        }
    }

    /**
     * Envía un mensaje a través del socket de comunicación.
     * @param msg   Mensaje que se desea transmitir.
     * @return  0 si no hubo problemas y otro valor sino.
     */
    public int sendLinea(String msg){

        PrintWriter out = null;
        ErrorHandler errorH = new ErrorHandler();

        try {
            out = new PrintWriter(this.cliente.getOutputStream(),true);
        } catch (IOException e){
            errorH.errorSendLineaDrep(this.control,e);
            return -1;
        }
        //Enviamos el mensaje
        out.println(msg);
        return 0;
    }


}
